package pl.vojna.ant_alg;

import java.util.Random;

public class Utils {

    public static Random random = new Random();
    private static final int PRIME = 1000000007;

    /**
     * Wyswietla tablice rozwiazan ze stalymi odstepami.
     * 
     * @param solution
     */
    public static void showSolution(int[] solution) {
        for (int i = 0; i < solution.length; i++) {
            System.out.print(String.format("%4d", solution[i]));
        }
        System.out.println();
    }

    /**
     * Oblicza koszt rozwiązania.
     * 
     * @param problem
     * @param solution
     * @return
     */
    public static int solutionCost(Problem problem, int[] solution) {
        int problemSize = problem.getSize();
        int[][] distances = problem.distances;
        int[][] flows = problem.flows;
        int result = 0;
        for (int i = 0; i < problemSize; i++) {
            for (int j = 0; j < problemSize; j++) {
                result += distances[i][j] * flows[solution[i]][solution[j]];
            }
        }
        return result;
    }

    public static double[][] heuristicInfo(Problem p) {
        int size = p.getSize();
        int d[] = new int[size];
        int f[] = new int[size];
        double result[][] = new double[size][size];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                d[i] += i != j ? p.distances[i][j] : 0;
                f[i] += i != j ? p.flows[i][j] : 0;
            }
        }

        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                result[i][j] = 1.0 / new Double((f[i] * d[j]));
            }
        }
        return result;

    }

    /**
     * Miesza tablice. (Collections.shuffle nie dziala dla typow prostych)
     * 
     * @param array
     */
    public static void shuffleArray(int[] array) {

        for (int i = array.length - 1; i >= 0; i--) {
            int index = random.nextInt(i + 1);
            int a = array[index];
            array[index] = array[i];
            array[i] = a;
        }
    }

    public static int swapFacilitiesCostDiff(Problem problem, int[] solution,
            int r, int s) {
        int[][] b = problem.distances;
        int[][] a = problem.flows;
        int n = problem.getSize();
        int fs = solution[s];
        int fr = solution[r];
        int result = b[r][r] * (a[fs][fs] - a[fr][fr]) + b[r][s]
                * (a[fs][fr] - a[fr][fs]) + b[s][r] * (a[fr][fs] - a[fs][fr])
                + b[s][s] * (a[fr][fr] - a[fs][fs]);
        for (int k = 0; k < n; k++) {

            if (k != r && k != s) {
                int fk = solution[k];
                result += b[k][r] * (a[fk][fs] - a[fk][fr]) + b[k][s]
                        * (a[fk][fr] - a[fk][fs]) + b[r][k]
                        * (a[fs][fk] - a[fr][fk]) + b[s][k]
                        * (a[fr][fk] - a[fs][fk]);
            }
        }
        return result;
    }

    public static int swapFacilitiesCostDiff(Problem problem, int[] solution,
            int r, int s, int u, int v, int diff_r_s) {
        int[][] b = problem.distances;
        int[][] a = problem.flows;
        int fu = solution[u];
        int fv = solution[v];
        int fs = solution[s];
        int fr = solution[r];
        return diff_r_s + (b[r][u] - b[r][v] + b[s][v] - b[s][u])
                * (a[fs][fu] - a[fs][fv] + a[fr][fv] - a[fr][fu])
                + (b[u][r] - b[v][r] + b[v][s] - b[u][s])
                * (a[fu][fs] - a[fv][fs] + a[fv][fr] - a[fu][fr]);
    }

    public static int solutionHash(int[] array) {
        int hash = 0;
        int n = array.length;
        for (int i = 0; i < array.length; i++) {
            hash = ((hash + array[i]) * n) % PRIME;
        }
        return hash;
    }

    public static int[] newIdPermutation(int length) {
        int[] result = new int[length];
        for (int i = 0; i < length; i++) {
            result[i] = i;
        }
        return result;
    }

    public static void p(String method, String test, int result,
            String optimalOrBestSolution) {
        System.out.println(String.format("[%s] %s: %10d / %s", method, test,
                result, optimalOrBestSolution));
    }

    public static String showArray(double a[][]) {
        int size = a.length;
        StringBuilder st = new StringBuilder();
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                st.append(a[i][j]);
                st.append(" ");
            }
            st.append("\n");
        }
        return st.toString();
    }

    public static String prepareForFile(int a[][]) {
        int size = a.length;
        StringBuilder st = new StringBuilder();
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                st.append(a[i][j]);
                st.append(" ");

            }
            st.append("\n");
        }
        return st.toString();
    }
}
